package com.yuanzong.wuliu.common.utils.file;

import com.yuanzong.wuliu.common.utils.UtilsSupport;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Calendar;

public class FileUtils {

    // 工具支持类
    private static UtilsSupport utilsSupport;

    public FileUtils(UtilsSupport utilsSupport) {
        this.utilsSupport = utilsSupport;
    }

    /**
     * 创建文件
     *
     * @param multipartFile 文件
     * @return 文件对象
     * @throws Exception
     * @author liujie
     */
    public static String create(MultipartFile multipartFile) throws Exception {
        // 获取类型
        String fileType = multipartFile.getContentType().substring(multipartFile.getContentType().indexOf("/") + 1);
        // 类型处理
        if (fileType.equals("vnd.android.package-archive")) {
            fileType = "apk";
        }
        String fileName = System.currentTimeMillis() + "." + fileType;
        // 获取年月日
        Calendar calendar = Calendar.getInstance();
        // 只拼接文件夹路径
        String path = utilsSupport.getFile_savePath() + "/" + calendar.get(Calendar.YEAR) + "/"
                + (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DATE);
        File fileSourcePath = new File(path);
        if (!fileSourcePath.exists()) {
            fileSourcePath.mkdirs();
        }
        // 文件名
        path = path + "/" + fileName;
        // 判断文件类型
        if (multipartFile.getContentType().contains("image")) {
            // 压缩
            Thumbnails.of(multipartFile.getInputStream())
                    .scale(1f)
                    .outputQuality(0.25f)
                    .toFile(path);
        } else {
            //保存
            multipartFile.transferTo(new File(path));
        }
        return utilsSupport.getFile_selectUrl() + "/" + calendar.get(Calendar.YEAR) + "/"
                + (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DATE) + "/" + fileName;
    }

    /**
     * 获取查询链接
     */
    public static String getFileSelectUrl() {
        return utilsSupport.getFile_selectUrl();
    }

    /*
     *	以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值
     */
    private static final Integer ZERO = 0;
    private static final Integer ONE_ZERO_TWO_FOUR = 1024;
    private static final Integer NINE_ZERO_ZERO = 900;
    private static final Integer THREE_TWO_SEVEN_FIVE = 3275;
    private static final Integer TWO_ZERO_FOUR_SEVEN = 2047;
    private static final Double ZERO_EIGHT_FIVE = 0.85;
    private static final Double ZERO_SIX = 0.6;
    private static final Double ZERO_FOUR_FOUR = 0.44;
    private static final Double ZERO_FOUR = 0.4;

    /**
     * 根据指定大小压缩图片
     *
     * @param imageBytes  源图片字节数组
     * @param desFileSize 指定图片大小，单位kb
     * @return 压缩质量后的图片字节数组
     */
    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) throws Exception {
        if (imageBytes == null || imageBytes.length <= ZERO || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR);
        while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) {
            ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
            Thumbnails.of(inputStream)
                    .scale(accuracy)
                    .outputQuality(accuracy)
                    .toOutputStream(outputStream);
            imageBytes = outputStream.toByteArray();
        }
        return imageBytes;
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) throws Exception {
        double accuracy;
        if (size < NINE_ZERO_ZERO) {
            accuracy = ZERO_EIGHT_FIVE;
        } else if (size < TWO_ZERO_FOUR_SEVEN) {
            accuracy = ZERO_SIX;
        } else if (size < THREE_TWO_SEVEN_FIVE) {
            accuracy = ZERO_FOUR_FOUR;
        } else {
            accuracy = ZERO_FOUR;
        }
        return accuracy;
    }

}
